//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ReadCathInfo.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
#include <fstream>
#include <stdexcept>

#include <zlib.h>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHLINE  10000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
namespace CathSpace {
  
  bool EqualDomain(TNode <CathCLF>* NodeT, void* ref = NULL) {

    return (!strcmp(NodeT->Info()->Domain()->Out(), (char*)ref))?true:false;

  }
  
  bool AlphDomain(CathCDDF* cathCDDF, void* ref) {

    return (strcmp(cathCDDF->Domain()->Out(), ((CathCDDF*)ref)->Domain()->Out()) < 0)?true:false;

  }
  
};
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ReadCathInfo::ReadCathInfo() {
  
  this->namefileCDDF          = new String ();
  this->namefileCLF           = new String ();

  this->namefileFASTA         = new String ();
  this->namefileFASTAProfile  = new String ();
  this->namefileDescription   = new String ();

  this->domainDescriptions    = new ListCathCDDF ();
  this->domainListCode        = new ListCathCLF ();
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ReadCathInfo::ReadCathInfo(const ReadCathInfo& readCathInfo) {
  
  this->namefileCDDF          = new String (readCathInfo.namefileCDDF);
  this->namefileCLF           = new String (readCathInfo.namefileCLF);

  this->namefileFASTA         = new String (readCathInfo.namefileFASTA);
  this->namefileFASTAProfile  = new String (readCathInfo.namefileFASTAProfile);
  this->namefileDescription   = new String (readCathInfo.namefileDescription);

  this->domainDescriptions    = new ListCathCDDF (readCathInfo.domainDescriptions);
  this->domainListCode        = new ListCathCLF (readCathInfo.domainListCode);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ReadCathInfo::ReadCathInfo(const ReadCathInfo* readCathInfo) {
  
  this->namefileCDDF          = new String (readCathInfo->namefileCDDF);
  this->namefileCLF           = new String (readCathInfo->namefileCLF);

  this->namefileFASTA         = new String (readCathInfo->namefileFASTA);
  this->namefileFASTAProfile  = new String (readCathInfo->namefileFASTAProfile);
  this->namefileDescription   = new String (readCathInfo->namefileDescription);

  this->domainDescriptions    = new ListCathCDDF (readCathInfo->domainDescriptions);
  this->domainListCode        = new ListCathCLF (readCathInfo->domainListCode);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ReadCathInfo::~ReadCathInfo() {
  
  if (this->namefileCDDF)         delete this->namefileCDDF;
  if (this->namefileCLF)          delete this->namefileCLF;

  if (this->namefileFASTA)        delete this->namefileFASTA;
  if (this->namefileFASTAProfile) delete this->namefileFASTAProfile;
  if (this->namefileDescription)  delete this->namefileDescription;

  if (this->domainDescriptions)   delete this->domainDescriptions;
  if (this->domainListCode)       delete this->domainListCode;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ReadCathInfo::NamefileCDDF (String* namefileCDDF) {
  
  if (namefileCDDF) this->namefileCDDF->In(namefileCDDF);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ReadCathInfo::NamefileCLF (String* namefileCLF) {
  
  if (namefileCLF) this->namefileCLF->In(namefileCLF);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ReadCathInfo::NamefileFASTA (String* namefileFASTA) {
  
  if (namefileFASTA) this->namefileFASTA->In(namefileFASTA);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ReadCathInfo::NamefileFASTAProfile (String* namefileFASTAProfile) {
  
  if (namefileFASTAProfile) this->namefileFASTAProfile->In(namefileFASTAProfile);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ReadCathInfo::NamefileDescription (String* namefileDescription) {
  
  if (namefileDescription) this->namefileDescription->In(namefileDescription);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ReadCathInfo::DomainDescriptions (ListCathCDDF* domainDescriptions) {
  
  if (domainDescriptions) *(this->domainDescriptions) = *(domainDescriptions);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ReadCathInfo::DomainListCode (ListCathCLF* domainListCode) {
  
  if (domainListCode) *(this->domainListCode) = *(domainListCode);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ReadCathInfo::NamefileCDDF (void) {
  
  return this->namefileCDDF;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ReadCathInfo::NamefileCLF (void) {
  
  return this->namefileCLF;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ReadCathInfo::NamefileFASTA (void) {
  
  return this->namefileFASTA;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ReadCathInfo::NamefileFASTAProfile (void) {
  
  return this->namefileFASTAProfile;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ReadCathInfo::NamefileDescription (void) {
  
  return this->namefileDescription;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListCathCDDF* ReadCathInfo::DomainDescriptions (void) {
  
  return this->domainDescriptions;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListCathCLF*  ReadCathInfo::DomainListCode (void) {
  
  return this->domainListCode;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ReadCathInfo::ReadDomainDescription (void) {
  
  if (!this->namefileCDDF || !this->namefileCDDF->Length()) return false;
  
  this->domainDescriptions->Namefile(this->namefileCDDF);
  
  return this->domainDescriptions->LoadData();
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ReadCathInfo::ReadDomainListCode (void) {
  
  if (!this->namefileCLF || !this->namefileCLF->Length()) return false;
  
  this->domainListCode->Namefile(this->namefileCLF);
  
  return this->domainListCode->LoadData();
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ReadCathInfo::MatchDomainInfo (void) {
  
  if (!this->domainDescriptions || !this->domainListCode) return false;
  
  this->domainDescriptions->ListDomainInfo()->SetInitial();
  cout << "Matching information about ";
  
  while (this->domainDescriptions->ListDomainInfo()->SetNext()) {
    
    CathCDDF* currentCDDF = this->domainDescriptions->ListDomainInfo()->GetCurrent();
    cout << currentCDDF->Domain()->Out();    
    for (int i = 0; i < currentCDDF->Domain()->Length(); i++)
      cout << "\b";
    CathCLF*  findCLF     = this->domainListCode->ListDomainCode()->FirstOcurrence(CathSpace::EqualDomain, currentCDDF->Domain()->Out());
    
    currentCDDF->CodeCathDomain(findCLF);
    
  }
  cout << endl;
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ReadCathInfo::OrderListDomain (void) {
  
  if (!this->domainDescriptions || !this->domainDescriptions->ListDomainInfo()->Length()) return false;
  
  this->domainDescriptions->ListDomainInfo()->QuickSortListByArray(CathSpace::AlphDomain, NULL);
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ReadCathInfo::OutFASTAFile (void) {
 
  if (!this->namefileFASTA || !this->namefileFASTA->Length()) return false;
  
  bool isGZFile = (this->namefileFASTA->Contain("gz"))?1:0;
  
  fstream file;
  gzFile  zipFile;
  
  char    buffer [LENGTHLINE + 1];
  
  if (isGZFile) zipFile = gzopen (this->namefileFASTA->Out(), "wb9");
  else          file.open (this->namefileFASTA->Out(), fstream::out);

  this->domainDescriptions->ListDomainInfo()->SetInitial();
  
  while (this->domainDescriptions->ListDomainInfo()->SetNext()) {
    
    CathCDDF* currentCDDF = this->domainDescriptions->ListDomainInfo()->GetCurrent();
    
    if (currentCDDF->CodeCathDomain())
      sprintf(buffer, ">%s (%s) - %s = [%s]\n%s\0", currentCDDF->Domain()->Out(), 
                                                    currentCDDF->Format()->Out(), 
                                                    currentCDDF->CodeCathDomain()->ToStringCode()->Out(), 
                                                    currentCDDF->ToStringSegment()->Out(),
                                                    currentCDDF->DomainSequence()->Out());
    else
      sprintf(buffer, ">%s (%s) = [%s]\n%s\0", currentCDDF->Domain()->Out(), 
                                               currentCDDF->Format()->Out(), 
                                               currentCDDF->ToStringSegment()->Out(),
                                               currentCDDF->DomainSequence()->Out());
    
    if (isGZFile) gzprintf(zipFile, "%s\n", buffer);
    else          file << buffer << endl;
    
  }

  if (isGZFile) gzclose(zipFile);
  else          file.close();
  
  return true;  
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ReadCathInfo::OutFASTAProfile (void) {
  
  if (!this->namefileFASTAProfile || !this->namefileFASTAProfile->Length()) return false;
  
  bool isGZFile = (this->namefileFASTAProfile->Contain("gz"))?1:0;
  
  fstream file;
  gzFile  zipFile;
  
  char    buffer [LENGTHLINE + 1];
  
  if (isGZFile) zipFile = gzopen (this->namefileFASTAProfile->Out(), "wb9");
  else          file.open (this->namefileFASTAProfile->Out(), fstream::out);

  this->domainDescriptions->ListDomainInfo()->SetInitial();
  
  while (this->domainDescriptions->ListDomainInfo()->SetNext()) {
    
    CathCDDF* currentCDDF = this->domainDescriptions->ListDomainInfo()->GetCurrent();
    
    if (currentCDDF->CodeCathDomain())
      sprintf(buffer, ">%s (%s) - %s = [%s]\n<%s\n+\n-\n:\n;\n!\0", currentCDDF->Domain()->Out(), 
                                                                    currentCDDF->Format()->Out(), 
                                                                    currentCDDF->CodeCathDomain()->ToStringCode()->Out(), 
                                                                    currentCDDF->ToStringSegment()->Out(),
                                                                    currentCDDF->DomainSequence()->Out());
    else
      sprintf(buffer, ">%s (%s) = [%s]\n<%s\n+\n-\n:\n;\n!\0", currentCDDF->Domain()->Out(), 
                                                               currentCDDF->Format()->Out(), 
                                                               currentCDDF->ToStringSegment()->Out(),
                                                               currentCDDF->DomainSequence()->Out());
    
    if (isGZFile) gzprintf(zipFile, "%s\n", buffer);
    else          file << buffer << endl;
    
  }

  if (isGZFile) gzclose(zipFile);
  else          file.close();
  
  return true;  
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ReadCathInfo::OutDescriptionDomain (void) {
  
  if (!this->namefileDescription || !this->namefileDescription->Length()) return false;
  
  bool isGZFile = (this->namefileDescription->Contain("gz"))?1:0;
  
  fstream file;
  gzFile  zipFile;
  
  char    buffer [LENGTHLINE + 1];
  
  if (isGZFile) zipFile = gzopen (this->namefileDescription->Out(), "wb9");
  else          file.open (this->namefileDescription->Out(), fstream::out);

  this->domainDescriptions->ListDomainInfo()->SetInitial();
  
  while (this->domainDescriptions->ListDomainInfo()->SetNext()) {
    
    CathCDDF* currentCDDF = this->domainDescriptions->ListDomainInfo()->GetCurrent();
    
    sprintf(buffer, "DOMAIN %s\nNAME   %s\nSOURCE %s\0", currentCDDF->Domain()->Out(), 
                                                         currentCDDF->Name()->Out(), 
                                                         currentCDDF->Source()->Out());
    
    if (isGZFile) gzprintf(zipFile, "%s\n", buffer);
    else          file << buffer << endl;
    
  }

  if (isGZFile) gzclose(zipFile);
  else          file.close();
  
  return true;  
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ReadCathInfo ReadCathInfo::operator= (const ReadCathInfo& readCathInfo) {
  
  this->namefileCDDF->In(readCathInfo.namefileCDDF);
  this->namefileCLF->In(readCathInfo.namefileCLF);

  this->namefileFASTA->In(readCathInfo.namefileFASTA);
  this->namefileFASTAProfile->In(readCathInfo.namefileFASTAProfile);
  this->namefileDescription->In(readCathInfo.namefileDescription);

  *(this->domainDescriptions) = *(readCathInfo.domainDescriptions);
  *(this->domainListCode)     = *(readCathInfo.domainListCode);
  
  return *this;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
